package cn.kgc.util.desensitization;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;

/**
 * @author wangyue
 * @version 1.0
 * 敏感数据序列化器
 */
@NoArgsConstructor
@AllArgsConstructor
public class SensitiveInfoSerializer extends JsonSerializer<String> implements ContextualSerializer {
    /**
     * 属性值的脱敏的类型
     */
    private DesensitizationType desensitizationType;
    /**
     * 属性值前多少位不被遮盖
     */
    private int prefixLen;
    /**
     * 属性值后多少位不被遮盖
     */
    private int suffixLen;

    /**
     * 将字符串类型的属性值进行脱敏
     */
    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        //s 就是当前要脱敏的属性的值
        if (StrUtil.isNotEmpty(s)) {
            //如果属性值不为空对数据进行脱敏
            switch (desensitizationType) {
                //判断当前要脱敏的数据的类型,如果是手机类型,使用工具类提供的方法进行脱敏
                case PHONE:
                    s = DesensitizedUtil.mobilePhone(s);
                    break;
                case CHINESE_NAME:
                    s = DesensitizedUtil.chineseName(s);
                    break;
                case ID_CARD:
                    s = DesensitizedUtil.idCardNum(s, prefixLen, suffixLen);
                    break;
                default:
                    //如果脱敏的数据类型是自定义的 调用StrUtil的hide方法对数据进行脱敏
                    s = StrUtil.hide(s, prefixLen, s.length() - suffixLen);
            }
        }
        jsonGenerator.writeString(s);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) {
        //beanProperty脱敏的属性的信息
        if (beanProperty != null) {
            //属性上的脱敏的注解信息(属性脱敏的规则)
            Desensitization annotation = beanProperty.getAnnotation(Desensitization.class);
            if (annotation != null) {
                //将属性上定义的脱敏规则 赋值给当前对象中属性
                return new SensitiveInfoSerializer(
                        annotation.type(),
                        annotation.prefixLen(),
                        annotation.suffixLen());
            }
        }
        return null;
    }
}
